package com.witmore.skyline.web.exception;

import com.witmore.skyline.web.controller.enums.WitmoreErrorCode;
import com.witmore.skyline.web.controller.vo.result.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.List;
import java.util.Objects;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private AsyncWeChatNotifier asyncWeChatNotifier;

    @Autowired
    private StackTraceFilter stackTraceFilter;

    @ExceptionHandler(Exception.class)
    public ResponseResult<?> handleException(Exception e) {
        // 发送企微通知
//        log.warn("4256738456kgjfhdghj:",stackTraceFilter.getSimplifiedStackTrace(e));
        asyncWeChatNotifier.sendSystemErrorToWeChatAsync(stackTraceFilter.getSimplifiedStackTrace(e));
        if (e instanceof WitmoreException) {
            return handleBusinessException((WitmoreException) e);
        }
        // 2. 参数验证异常（虽然应该被前面的处理器捕获，但这里做二次保障）
        if (e instanceof BindException) {
            return handleValidationException(e);
        }
        // 3. 其他所有未处理异常
        log.error("系统异常: ", e);
        return ResponseResult.fail(WitmoreErrorCode.SYSTEM_ERROR.getCode(), e.getMessage());
    }

    /**
     * 处理业务异常
     */
    @ExceptionHandler(WitmoreException.class)
    public ResponseResult<?> handleBusinessException(WitmoreException e) {
        int code = e == null ? WitmoreErrorCode.SYSTEM_ERROR.getCode() : e.getErrorCode().getCode();
        String message = e == null ? WitmoreErrorCode.SYSTEM_ERROR.getMessage() : e.getMessage();
        return ResponseResult.fail(code, message);
    }

    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public ResponseResult<?> handleValidationException(Exception e) {
        String errorMessage = "参数验证失败";
        if (e instanceof MethodArgumentNotValidException ex) {
            List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
            FieldError fieldError = fieldErrors.get(0);
            errorMessage = fieldError.getDefaultMessage();
        } else if (e instanceof BindException ex) {
            List<FieldError> fieldErrors = ex.getBindingResult().getFieldErrors();
            FieldError fieldError = fieldErrors.get(0);
            errorMessage = fieldError.getDefaultMessage();
        }
        return ResponseResult.fail(WitmoreErrorCode.PARAM_ERROR.getCode(), errorMessage);
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseResult<String> handleDeserializationError(HttpMessageNotReadableException ex) {
        // 可以根据需要提取更详细的错误信息
        return ResponseResult.fail(WitmoreErrorCode.SYSTEM_ERROR.getCode(), ex.getMessage());
    }


    /**
     * 处理请求参数类型不匹配错误（如传递了错误的参数类型）
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseResult<Void> handleTypeMismatch(MethodArgumentTypeMismatchException ex) {
        String name = ex.getName();
        String type = Objects.requireNonNull(ex.getRequiredType()).getSimpleName();
        String value = ex.getValue() != null ? ex.getValue().toString() : "";
        String message = String.format("参数 '%s' 应为类型 '%s'，但接收到值为 '%s'", name, type, value);
        return ResponseResult.fail(WitmoreErrorCode.PARAM_ERROR.getCode(), message);
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResponseResult<Void> handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
        String parameterName = ex.getParameterName();
        String parameterType = ex.getParameterType();
        String message = String.format("缺少参数 '%s'，类型为 '%s'", parameterName, parameterType);
        return ResponseResult.fail(WitmoreErrorCode.PARAM_ERROR.getCode(), message);
    }
}
